package pluginLoader;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.Collections;

import javax.swing.JOptionPane;

import compatibilite.AExcelMiniPlugin;
import compatibilite.IExcelMiniPlugin;

/**
 * 
 * @author Axel
 * Classe fournissant la méthode utilisée pour le chargement dynamique.
 */
public class ExcelMiniLoader{
         public ExcelMiniLoader(){}
         /**
          * Méthode analysant un fichier Jar afin de déterminer si celui-ci contient 
          * un plugin compatible avec l'application.
          * 
          * @param pluginJar Fichier Jar du plugin.
          * @return     Instance du plugin ci celui-ci est compatible. 
          *             Sinon la méthode renvoie null.
          * @throws IOException
          * @throws ClassNotFoundException
          * @throws InstantiationException
          * @throws IllegalAccessException
          */
                public IExcelMiniPlugin chargerPlugin(File pluginJar) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{
                        JarFile jarFile = null;
                        URLClassLoader chargeur = null;
                        URL lienJar = null;
                        Class<?> classe = null;
                        String nomClasse = null;
                        IExcelMiniPlugin plugin = null;
                        // je verrifie que le fichier est bien un jar
                        if(pluginJar.getName().endsWith(".jar")){
                        		//je récupère son lien URL afin de pouvoir y acceder plus tard
                                lienJar = pluginJar.toURI().toURL();
                                chargeur = new URLClassLoader(new URL[]{lienJar});
                                jarFile = new JarFile(pluginJar);
                                //pour chaque entrée du jar
                                for(JarEntry je : Collections.list(jarFile.entries())){
                                        nomClasse=je.getName();
                                        //si il s'agit d'une classe qui ne concerne pas le package compatibilité
                                        if(nomClasse.endsWith(".class") && !nomClasse.contains("compatibilite")){
                                        		//j'enlève le .class et je remplace les "/" par des points afin de reconstituer
                                        		//le "binary name" de la classe
                                                nomClasse =(nomClasse.substring(0,nomClasse.lastIndexOf(".")).replaceAll("/", "."));
                                                //je traite que les classes faisant partie d'un package
                                                if(nomClasse.contains(".")){
                                                        try{
                                                        		//je récupère l'objet Class de la classe
                                                                classe = Class.forName(nomClasse, true, chargeur);
                                                        }
                                                        //si jamais des classes sont introuvable j'averti l'utilisateur que le plugin est endommagé
                                                        catch(ClassNotFoundException e){
                                                                JOptionPane.showMessageDialog(null, "La classe : "+nomClasse+" est introuvable.",
                                                                                "Echec de chargement", JOptionPane.ERROR_MESSAGE);}
                                                        if(classe!= null){
                                                        	//si on a réussi à récuprer le Class il faut maintenat verrifier si il hérite bien de l'api
                                                                        if(classe.getSuperclass()!=null){
                                                                                if(classe.getSuperclass().equals(AExcelMiniPlugin.class)){
                                                                                        try{    
                                                                                        	//j'ai trouvé la classe principale du plugin, 
                                                                                        	//c'est celle que je renvoie à l'application pour l'installation
                                                                                                plugin = (IExcelMiniPlugin)classe.newInstance();
                                                                                        }
                                                                                        //j'informe l'utilisateur qu'il est impossible de construire le plugin,
                                                                                        //ça peut arriver si il n'y a pas de constructeur vide
                                                                                        catch(InstantiationException e){
                                                                                                JOptionPane.showMessageDialog(null, "Impossible de construire le plugin.",
                                                                                                                "Echec d'instanciation", JOptionPane.ERROR_MESSAGE);
                                                                                        }
                                                                                }
                                                                        }
                                                                }
                                                }
                                        }
                                }
                                //lireration des ressources
                                jarFile.close();
                        }
                        return plugin;
                }
}
